package com.xindacloud.sms.console.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xindacloud.sms.console.result.Result;
import com.xindacloud.sms.console.result.ResultGenerator;
import com.xindacloud.sms.console.system.dto.*;
import com.xindacloud.sms.console.system.entity.*;
import com.xindacloud.sms.console.system.mapper.SmsRoleMapper;
import com.xindacloud.sms.console.system.mapper.SmsUserMapper;
import com.xindacloud.sms.console.system.mapper.SmsUserRoleMapper;
import com.xindacloud.sms.console.system.service.ISmsPricingService;
import com.xindacloud.sms.console.system.service.ISmsUserAllowOperatorService;
import com.xindacloud.sms.console.system.service.ISmsUserService;
import com.xindacloud.sms.console.system.vo.UserRoleVO;
import com.xindacloud.sms.console.system.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author czc
 * @since 2019-10-08
 */
@Service
@Slf4j
public class SmsUserServiceImpl extends ServiceImpl<SmsUserMapper, SmsUser> implements ISmsUserService {

    @Autowired
    SmsUserMapper smsUserMapper;

    @Autowired
    ISmsPricingService pricingService;

    @Autowired
    ISmsUserAllowOperatorService userAllowOperatorService;

    @Override
    public SmsUser login(UserLoginDTO userDTO) {
        QueryWrapper<SmsUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", userDTO.getUsername());
        queryWrapper.eq("password", userDTO.getPassword());
        queryWrapper.eq("status", 0);
        final SmsUser smsUser = this.getOne(queryWrapper);
        if (Objects.nonNull(smsUser)) {
            //smsUser.setStatus(0);
            this.updateById(smsUser);
        }
        return smsUser;

        /*if (smsUser != null) {
            String pwdInDb = smsUser.getPassword();
            boolean isPasswordCorrect = false;
            try {
                isPasswordCorrect = SecurityUtil.validPassword(userDTO.getPassword(), pwdInDb);
            } catch (Exception e) {
                return ResultGenerator.genServerFailResult("解密失败，再试一次！");
            }
            if (isPasswordCorrect) {
                smsUser.setStatus(0);
                if (this.updateById(smsUser)) {
                    return ResultGenerator.genSuccessResult(smsUser);
                } else {
                    return ResultGenerator.genServerFailResult("修改用户状态失败，请重新登录！");
                }
                
            } else {
                return ResultGenerator.genServerFailResult("无效的用户名和密码！");
            }
        } else {
            return ResultGenerator.genClientFailResult(HttpStatus.NOT_FOUND, "用户不存在！");
        }*/

    }

    @Override
    public Result logout(SmsUser smsUser) {
        if (smsUser != null) {
            smsUser.setStatus(1);
            if (this.updateById(smsUser)) {
                return ResultGenerator.genSuccessResult("登出成功！");
            } else {
                return ResultGenerator.genServerFailResult("登出失败！");
            }
        } else {
            return ResultGenerator.genClientFailResult(HttpStatus.NOT_FOUND, "用户不存在！");
        }
    }

    @Override
    public Result getUserList(UserDTO userDTO) {
        QueryWrapper<SmsUserRole> userRoleWrapper = new QueryWrapper<>();
        userRoleWrapper.eq("user_id", userDTO.getParentUserId());
        List<SmsUserRole> surList = smsUserRoleMapper.selectList(userRoleWrapper);
        Set<Integer> iSet = new HashSet<>();
        for (SmsUserRole smsUserRole : surList) {
            QueryWrapper<SmsRole> roleWrapper = new QueryWrapper<>();
            roleWrapper.eq("role_id", smsUserRole.getRoleId());
            List<SmsRole> smsRoleList = smsRoleMapper.selectList(roleWrapper);
            for (SmsRole smsRole : smsRoleList) {
                iSet.add(smsRole.getRolePrivLevel());
            }
        }
        Integer roleLevel = 0;
        if (iSet != null && iSet.size() > 0) {
            roleLevel = Collections.max(iSet);
        }

        Page<SmsUser> page = new Page<>(userDTO.getPageNum(), userDTO.getPageSize());
        QueryWrapper<SmsUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 0);
        if (userDTO.getApplyStatus() != null) {
            queryWrapper.eq("apply_status", userDTO.getApplyStatus());
        }
        if (roleLevel.equals(1)) {
            queryWrapper.eq("parent_user_id", userDTO.getParentUserId()).or().eq("user_id", userDTO.getParentUserId());

        } else if (roleLevel.equals(0)) {
            return ResultGenerator.genSuccessResult();
        }
        IPage<SmsUser> uPage = this.page(page, queryWrapper);
        List<SmsUser> rList = uPage.getRecords();
        List<UserDTO> urList = new ArrayList<>();
        for (SmsUser user : rList) {
            UserDTO sur = new UserDTO();
            BeanUtils.copyProperties(user, sur);
            List<SmsRoleDTO> roleDto = new ArrayList<>();
            QueryWrapper<SmsUserRole> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", user.getUserId());
            List<SmsUserRole> roles = smsUserRoleMapper.selectList(wrapper);
            for (SmsUserRole role : roles) {
                SmsRole smsRole = smsRoleMapper.selectById(role.getRoleId());
                SmsRoleDTO smsRoleDTO = new SmsRoleDTO();
                BeanUtils.copyProperties(smsRole, smsRoleDTO);
                roleDto.add(smsRoleDTO);
            }
            sur.setRoles(roleDto);
            urList.add(sur);
        }
        IPage<UserDTO> dtoPage = new Page<>();
        dtoPage.setCurrent(uPage.getCurrent());
        dtoPage.setPages(uPage.getPages());
        dtoPage.setRecords(urList);
        dtoPage.setSize(uPage.getSize());
        dtoPage.setTotal(uPage.getTotal());
        return ResultGenerator.genSuccessResult(dtoPage);
    }

    @Override
    public Result addOrUpdateUser(SmsUser smsUser) {

        if (Objects.nonNull(smsUser.getUserId()) && smsUser.getUserId() != 0) {
            if (this.updateById(smsUser)) {
                userAllowOperatorService.updateDisplayCurrencyById(smsUser.getUserId(), smsUser.getDisplayCurrency());
                return ResultGenerator.genSuccessResult("修改用户成功！");
            } else {
                return ResultGenerator.genServerFailResult("修改用户失败！");
            }

        } else {
            QueryWrapper<SmsUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", smsUser.getUsername());
            SmsUser hadEntity = this.getOne(queryWrapper);
            if (hadEntity != null) {
                return ResultGenerator.genServerFailResult("用户名已存在，新增用户失败！");
            }
            if (this.save(smsUser)) {
                return ResultGenerator.genSuccessResult("新增用户成功！");
            } else {
                return ResultGenerator.genServerFailResult("新增用户失败！");
            }
        }

    }


    @Override
    public List<SmsUser> querySmsUserListByIds(List<Integer> ids) {
        return lambdaQuery()
                .in(CollectionUtils.isNotEmpty(ids), SmsUser::getUserId, ids)
                .list();
    }

    @Override
    public List<UserVO> queryUserInfoByName(String username) {

        final List<SmsUser> list = lambdaQuery()
                .like(SmsUser::getUsername, username)
                .list();
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream()
                    .map(rs -> UserVO.builder()
                            .userId(rs.getUserId())
                            .username(rs.getUsername())
                            .build()).collect(Collectors.toList());
        }
        return null;
    }

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private SmsUserRoleMapper smsUserRoleMapper;
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private SmsRoleMapper smsRoleMapper;

    @Override
    public Result addOrUpdateUserRoles(SmsUserRolesDTO smsUserRolesDTO) {
        QueryWrapper<SmsUserRole> wrapper = new QueryWrapper<>();
        if (smsUserRolesDTO.getUserId() != null) {
            wrapper.eq("user_id", smsUserRolesDTO.getUserId());
        } else {
            return ResultGenerator.genServerFailResult("分配角色失败！请传用户id");
        }
        List<SmsUserRole> urList = smsUserRoleMapper.selectList(wrapper);
        if (urList != null) {
            smsUserRoleMapper.delete(wrapper);
        }
        if (smsUserRolesDTO.getRoleIds() != null) {
            for (Integer roleId : smsUserRolesDTO.getRoleIds()) {
                SmsUserRole entity = new SmsUserRole();
                entity.setRoleId(roleId);
                entity.setUserId(smsUserRolesDTO.getUserId());
                smsUserRoleMapper.insert(entity);
                if (roleId.equals(6)) {
                    SmsUser smsUser = new SmsUser();
                    smsUser.setUserId(smsUserRolesDTO.getUserId());
                    smsUser.setParentUserId(0);
                    this.updateById(smsUser);
                }

            }
        } else {
            return ResultGenerator.genServerFailResult("分配角色失败！请角色id");
        }
        return ResultGenerator.genSuccessResult("分配角色成功！");
    }

    @Override
    public Result deleteUsers(UserDeleteDTO userDeleteDTO) {
        final boolean update = lambdaUpdate()
                .set(SmsUser::getStatus, true)
                .in(SmsUser::getUserId, userDeleteDTO.getIds())
                .update();
        //this.removeByIds(userDeleteDTO.getIds())
        if (update) {
            return ResultGenerator.genSuccessResult("删除用户成功！");
        } else {
            return ResultGenerator.genServerFailResult("删除用户失败！");
        }
    }

    public Boolean syncPricingByUserId(Integer userId) {
        boolean isSuccess = false;
        final List<SmsPricing> smsPricingList = pricingService.queryPricingList();
        if (CollectionUtils.isNotEmpty(smsPricingList)) {
            List<SmsUserAllowOperator> insertList = new ArrayList<>();
            //List<SmsUserAllowOperator> updateList = new ArrayList<>();
            final List<SmsUserAllowOperator> allowOperators = smsPricingList.stream()
                    .map(map -> {
                        SmsUserAllowOperator userAllowOperator = new SmsUserAllowOperator();
                        BeanUtils.copyProperties(map, userAllowOperator);
                        userAllowOperator.setStatus(true);
                        userAllowOperator.setUserId(userId);
                        return userAllowOperator;

                    }).collect(Collectors.toList());


            if (CollectionUtils.isNotEmpty(allowOperators)) {
                final List<String> operatorIds = allowOperators.stream()
                        .map(SmsUserAllowOperator::getOperatorId)
                        .collect(Collectors.toList());

                final List<SmsUserAllowOperator> existRecordList = userAllowOperatorService.querySmsUserAllowOperatorList(operatorIds, userId);
                if (CollectionUtils.isNotEmpty(existRecordList)) {
                    final List<String> existOperatorIds = existRecordList.stream()
                            .map(SmsUserAllowOperator::getOperatorId)
                            .collect(Collectors.toList());
                    for (SmsUserAllowOperator sourceRs : allowOperators) {
                        if (existOperatorIds.contains(sourceRs.getOperatorId())) {
                            //updateList.add(sourceRs);
                        } else {
                            insertList.add(sourceRs);
                        }
                    }
                } else {
                    insertList.addAll(allowOperators);
                }
               /* if (CollectionUtils.isNotEmpty(updateList)) {
                    log.info("修改成本价，默认价条数:{}", updateList.size());
                    userAllowOperatorService.updateUserAllowOperatorFor(updateList);
                }*/
                if (CollectionUtils.isNotEmpty(insertList)) {
                    final List<SmsUser> smsUsers = this.querySmsUserListByIds(Arrays.asList(userId));
                    final List<SmsUserAllowOperator> list = insertList.stream().peek(rs -> {
                        rs.setCurrency(smsUsers.get(0).getDisplayCurrency());
                        rs.setUserId(userId);
                    })
                            .collect(Collectors.toList());
                    isSuccess = userAllowOperatorService.saveSmsUserAllowOperatorBatch(list);
                }
            }
        }
        return isSuccess;
    }

    @Override
    public Result getUserDetail(Integer userId) {
        SmsUser user = this.getById(userId);
        if (user != null) {
            return ResultGenerator.genSuccessResult(user);
        } else {
            return ResultGenerator.genServerFailResult("获取用户详情失败！");
        }
    }


    @Override
    public List<SmsUserAllowOperator> queryUserAllowOperatorByUserId(Integer userId, QueryPricingByConditionsDTO conditionsDTO) {

        List<SmsUserAllowOperator> smsUserAllowOperators;
        final Integer role = userAllowOperatorService.getRole(userId);
        if (Objects.equals(2, role) || Objects.equals(1, role)) {
            smsUserAllowOperators = getSourcePricingList(conditionsDTO);
        } else {
            Integer parentId = querySmsUserListByIds(Collections.singletonList(userId)).get(0).getParentUserId();
            smsUserAllowOperators = userAllowOperatorService.queryUserAllowOperatorByParentId(parentId, conditionsDTO);
            if (CollectionUtils.isEmpty(smsUserAllowOperators)) {
                smsUserAllowOperators = getSourcePricingList(conditionsDTO);
            }
        }
        return smsUserAllowOperators;
    }

    private List<SmsUserAllowOperator> getSourcePricingList(QueryPricingByConditionsDTO conditionsDTO) {
        return pricingService.queryUserAllowOperatorByConditions(conditionsDTO).stream()
                .map(map -> {
                    SmsUserAllowOperator userAllowOperator = new SmsUserAllowOperator();
                    BeanUtils.copyProperties(map, userAllowOperator);
                    userAllowOperator.setAllowOperatorId(UUID.randomUUID().toString().replaceAll("-", ""));
                    return userAllowOperator;

                }).collect(Collectors.toList());
    }

    @Override
    public Boolean syncUserPricingByOperatorIds(Integer userId, List<String> operatorIds) {
        boolean isSuccess = false;
        List<SmsUserAllowOperator> insertList = new ArrayList<>();
        final QueryPricingByConditionsDTO build = QueryPricingByConditionsDTO.builder().operatorIds(operatorIds).build();
        final List<SmsUserAllowOperator> smsUserAllowOperators = queryUserAllowOperatorByUserId(userId, build);

        final List<SmsUserAllowOperator> existRecordList = userAllowOperatorService.querySmsUserAllowOperatorList(operatorIds, userId);
        if (CollectionUtils.isNotEmpty(existRecordList)) {
            final List<String> existOperatorIds = existRecordList.stream()
                    .map(SmsUserAllowOperator::getOperatorId)
                    .collect(Collectors.toList());
            for (SmsUserAllowOperator sourceRs : smsUserAllowOperators) {
                final boolean exist = !existOperatorIds.contains(sourceRs.getOperatorId());
                if (exist) {
                    insertList.add(sourceRs);
                }
            }
        } else {
            insertList.addAll(smsUserAllowOperators);
        }
        if (CollectionUtils.isNotEmpty(insertList)) {
            final List<SmsUser> smsUsers = this.querySmsUserListByIds(Arrays.asList(userId));
            final List<SmsUserAllowOperator> allowOperators = smsUserAllowOperators.stream()
                    .peek(rs -> {
                        rs.setUserId(userId);
                        rs.setCurrency(smsUsers.get(0).getDisplayCurrency());
                    })
                    .collect(Collectors.toList());
            isSuccess = userAllowOperatorService.saveSmsUserAllowOperatorBatch(allowOperators);
        }
        return isSuccess;
    }

    @Override
    public List<UserRoleVO> queryUserRoleList(Integer userId) {
        return smsUserMapper.queryUserRoleList(userId);
    }
}
